home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cocktail
/
lalr.lha
/
lalr
/
src
/
GenLang.mi
< prev
next >
Wrap
Text File
|
1992-08-18
|
14KB
|
499 lines
(* generate source parts of the parser *)
(* $Id: GenLang.mi,v 1.10 1992/08/07 15:22:49 grosch rel $ *)
(* $Log: GenLang.mi,v $
* Revision 1.10 1992/08/07 15:22:49 grosch
* allow several scanner and parsers; extend module Errors
*
* Revision 1.9 1992/01/30 14:08:30 grosch
* redesign of interface to operating system
*
* Revision 1.8 1991/12/04 16:23:39 grosch
* unified escape conventions for all tools
*
* Revision 1.7 1991/11/21 14:53:14 grosch
* new version of RCS on SPARC
*
* Revision 1.6 90/12/20 19:26:42 grosch
* removed time stamp from tables
*
* Revision 1.5 90/09/20 17:52:31 grosch
* calmed down lint
*
* Revision 1.4 90/06/12 17:17:23 grosch
* layout improvements
*
* Revision 1.3 90/06/12 16:54:16 grosch
* renamed main program to lalr, added { } for actions, layout improvements
*
* Revision 1.2 89/05/02 14:36:38 vielsack
* $$ is used instead of $0
* $0, $-1, $-2, .. are legal now
* attribute access is changed for the stacks are now dynamic arrays
*
* Revision 1.1 89/01/12 18:09:43 vielsack
* line number is printed before an action is output
*
* Revision 1.0 88/10/04 14:36:23 vielsack
* Initial revision
*
*)
IMPLEMENTATION MODULE GenLang; (* Erzeugung von Modula2- oder C-Quelltexten *)
FROM Automaton IMPORT tIndex, tStateIndex, tProdIndex, tProduction, ProdIndex, ProdArrayPtr, NextProdIndex;
FROM Compress IMPORT NTableSize, TableSize;
FROM DynArray IMPORT ReleaseArray;
FROM ArgCheck IMPORT LineFlag;
FROM Gen IMPORT NonTermOffset, FirstTerminal, LastTerminal, FirstSymbol,
LastSymbol, FirstReadState, LastReadState, FirstReadTermState,
LastReadTermState, FirstReadNonTermState, LastReadNonTermState,
FirstReduceState, LastReduceState, StartState, StopState,
CaseLabels, CaseFlag;
FROM IO IMPORT tFile, WriteNl, WriteI, WriteS, WriteC;
FROM Lists IMPORT tList, IsEmpty, Tail, Head;
FROM Strings IMPORT tStringIndex, tString, Char, Length;
FROM StringMem IMPORT tStringRef;
IMPORT StringMem; (* GetString *)
FROM Idents IMPORT tIdent, GetString;
FROM SYSTEM IMPORT TSIZE, ADR;
FROM TokenTab IMPORT PosType, TokenError, Vocabulary, TokenToSymbol;
FROM WriteTok IMPORT tLanguage, Language, SourceFileName;
PROCEDURE WriteConstants (f: tFile); (* Ausgabe der Konstanten *)
BEGIN
IF Language = Modula2 THEN
WriteS (f, ' yyFirstTerminal = ');
WriteI (f, FirstTerminal, 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyLastTerminal = ');
WriteI (f, LastTerminal, 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyFirstSymbol = ');
WriteI (f, FirstSymbol, 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyLastSymbol = ');
WriteI (f, LastSymbol, 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyTableMax = ');
WriteI (f, TableSize, 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyNTableMax = ');
WriteI (f, NTableSize, 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyFirstReadState = ');
WriteI (f, FirstReadState, 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyLastReadState = ');
WriteI (f, LastReadState, 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyFirstReadTermState = ');
WriteI (f, FirstReadTermState, 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyLastReadTermState = ');
WriteI (f, LastReadTermState, 0); WriteC (f, ';'); WriteNl(f);
(* WriteS (f, ' yyFirstReadNontermState = ');
WriteI (f, FirstReadNonTermState, 0); WriteC (f, ';'); WriteNl(f); *)
WriteS (f, ' yyLastReadNontermState = ');
WriteI (f, LastReadNonTermState, 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyFirstReduceState = ');
WriteI (f, FirstReduceState, 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyLastReduceState = ');
WriteI (f, LastReduceState, 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyStartState = ');
WriteI (f, StartState(), 0); WriteC (f, ';'); WriteNl(f);
WriteS (f, ' yyStopState = ');
WriteI (f, StopState, 0); WriteC (f, ';'); WriteNl(f);
ELSE (* Language = C *)
WriteS (f, '# define yyFirstTerminal ');
WriteI (f, FirstTerminal, 0); WriteNl(f);
WriteS (f, '# define yyLastTerminal ');
WriteI (f, LastTerminal, 0); WriteNl(f);
(* WriteS (f, '# define yyFirstSymbol ');
WriteI (f, FirstSymbol, 0); WriteNl(f);
WriteS (f, '# define yyLastSymbol ');
WriteI (f, LastSymbol, 0); WriteNl(f); *)
WriteS (f, '# define yyTableMax ');
WriteI (f, TableSize, 0); WriteNl(f);
WriteS (f, '# define yyNTableMax ');
WriteI (f, NTableSize, 0); WriteNl(f);
WriteS (f, '# define yyFirstReadState ');
WriteI (f, FirstReadState, 0); WriteNl(f);
WriteS (f, '# define yyLastReadState ');
WriteI (f, LastReadState, 0); WriteNl(f);
WriteS (f, '# define yyFirstReadTermState ');
WriteI (f, FirstReadTermState, 0); WriteNl(f);
WriteS (f, '# define yyLastReadTermState ');
WriteI (f, LastReadTermState, 0); WriteNl(f);
(* WriteS (f, '# define yyFirstReadNontermState ');
WriteI (f, FirstReadNonTermState, 0); WriteNl(f); *)
WriteS (f, '# define yyLastReadNontermState ');
WriteI (f, LastReadNonTermState, 0); WriteNl(f);
WriteS (f, '# define yyFirstReduceState ');
WriteI (f, FirstReduceState, 0); WriteNl(f);
WriteS (f, '# define yyLastReduceState ');
WriteI (f, LastReduceState, 0); WriteNl(f);
WriteS (f, '# define yyStartState ');
WriteI (f, StartState(), 0); WriteNl(f);
WriteS (f, '# define yyStopState ');
WriteI (f, StopState, 0); WriteNl(f);
END;
END WriteConstants;
PROCEDURE WriteReduceCode (f:tFile); (* Ausgabe des Codes fuer die Reduktionen *)
VAR
label: tStateIndex;
labels: INTEGER;
cases: INTEGER;
index: tProdIndex;
prod: tProduction;
maxProdIndex: tProdIndex;
u: LONGINT;
BEGIN
label := FirstReduceState;
labels := 0;
cases := 1;
index := 0;
IF CaseLabels > 0 THEN
INC (label, CaseLabels);
OpenCase (f, label);
ELSIF Language = Modula2 THEN
WriteS (f, 'CASE yyState OF');
WriteNl (f);
ELSE (* Language = C *)
WriteS (f, 'switch (yyState) {');
WriteNl (f);
END;
maxProdIndex := ProdIndex;
WHILE index < maxProdIndex DO
IF CaseLabels > 0 THEN
IF labels >= CaseLabels THEN
INC (label, CaseLabels);
NextCase (f, label);
INC (cases);
labels := 0;
END;
INC (labels);
END;
prod := ADR (ProdArrayPtr^[index]);
(* States ausgeben *)
WITH prod^.Reduce DO
IF Language = Modula2 THEN
WriteS (f, ' | ');
WriteI (f, Array^[1], 0);
ELSE (* Language = C *)
WriteS (f, 'case ');
WriteI (f, Array^[1], 0);
WriteC (f, ':');
END;
IF NOT CaseFlag THEN
FOR u := 2 TO Used DO
IF Language = Modula2 THEN
WriteC (f, ',');
WriteI (f, Array^[u], 0);
ELSE (* Language = C *)
WriteNl (f);
WriteS (f, 'case ');
WriteI (f, Array^[u], 0);
WriteC (f, ':');
END;
END;
END;
IF Language = Modula2 THEN WriteC (f, ':'); END;
WriteProdComment (f, prod);
IF index = 0 THEN (* Endzustand *)
IF Language = Modula2 THEN
WriteS (f, ' DynArray.ReleaseArray (yyStateStack, yyStateStackSize, SYSTEM.TSIZE (yyTableElmt));');
WriteNl (f);
WriteS (f, ' DynArray.ReleaseArray (yyAttributeStack, yyAttrStackSize, SYSTEM.TSIZE (tParsAttribute));');
WriteNl (f);
WriteS (f, ' RETURN yyErrorCount;');
WriteNl (f);
ELSE (* Language = C *)
WriteS (f, ' ReleaseArray ((char * *) & yyStateStack, & yyStateStackSize, sizeof (yyStateRange));');
WriteNl (f);
WriteS (f, ' ReleaseArray ((char * *) & yyAttributeStack, & yyAttrStackSize, sizeof (tParsAttribute));');
WriteNl (f);
WriteS (f, ' return yyErrorCount;');
WriteNl (f);
END;
ELSE
IF Language = Modula2 THEN
WriteS (f, ' DEC (yyStackPtr, ');
WriteI (f, prod^.Len, 0);
WriteS (f, '); yyNonterminal := ');
WriteI (f, prod^.Left-NonTermOffset, 0);
WriteS (f, ';');
WriteNl (f);
ELSE (* Language = C *)
WriteS (f, ' yyStateStackPtr -=');
WriteI (f, prod^.Len, 0);
WriteS (f, '; yyAttrStackPtr -=');
WriteI (f, prod^.Len, 0);
WriteS (f, '; yyNonterminal = ');
WriteI (f, prod^.Left-NonTermOffset, 0);
WriteS (f, '; {');
WriteNl (f);
END;
END;
ReleaseArray (Array, Count, TSIZE (tIndex));
END;
(* semantische Aktion ausgeben *)
WriteSemanticAction (f, prod^.Act, prod^.Len, prod^.ActPos);
IF (index # 0) AND (Language = C) THEN
WriteS (f, '} break;'); WriteNl (f);
END;
index := NextProdIndex(index);
END;
IF CaseLabels > 0 THEN
CloseCase (f, cases);
ELSIF Language = Modula2 THEN
WriteS (f, 'END;');
WriteNl (f);
ELSE (* Language = C *)
WriteS (f, '}');
WriteNl (f);
END;
END WriteReduceCode;
PROCEDURE OpenCase (f: tFile; label: tStateIndex);
BEGIN
IF Language = Modula2 THEN
WriteS (f, 'CASE yyState OF');
WriteNl (f);
ELSE (* Language = C *)
IF label <= LastReduceState THEN
WriteS (f, 'if (yyState < ');
WriteI (f, label, 0);
WriteS (f, ') ');
END;
WriteS (f, 'switch (yyState) {');
WriteNl (f);
END;
END OpenCase;
PROCEDURE NextCase (f: tFile; label: tStateIndex);
BEGIN
IF Language = Modula2 THEN
WriteS (f, 'ELSE CASE yyState OF');
WriteNl (f);
ELSE (* Language = C *)
WriteS (f, '} else ');
IF label <= LastReduceState THEN
WriteS (f, 'if (yyState < ');
WriteI (f, label, 0);
WriteS (f, ') ');
END;
WriteS (f, 'switch (yyState) {');
WriteNl (f);
END;
END NextCase;
PROCEDURE CloseCase (f: tFile; cases: INTEGER);
BEGIN
IF Language = Modula2 THEN
WHILE cases > 0 DO
WriteS (f, 'END; (* additional CASE *)');
WriteNl (f);
DEC (cases);
END;
ELSE (* Language = C *)
WriteS (f, '}');
WriteNl (f);
END;
END CloseCase;
PROCEDURE WriteSemanticAction (f: tFile; a: tList; len: CARDINAL; pos: PosType);
VAR
c: CHAR;
s: tString;
i: tStringIndex;
i1, i2: tStringIndex;
AttrIndex: CARDINAL;
negative: BOOLEAN;
Delimiter : CHAR;
BEGIN
IF pos.Line # 0 THEN
IF Language = Modula2 THEN
WriteS (f, '(* line ');
WriteI (f, pos.Line, 0);
WriteS (f, ' "');
WriteS (f, SourceFileName);
WriteS (f, '" *)');
WriteNl (f);
ELSE (* Language = C *)
IF LineFlag THEN
WriteS (f, '# line ');
WriteI (f, pos.Line, 0);
WriteS (f, ' "');
WriteS (f, SourceFileName);
WriteC (f, '"');
WriteNl (f);
ELSE
WriteS (f, '/* line ');
WriteI (f, pos.Line, 0);
WriteS (f, ' "');
WriteS (f, SourceFileName);
WriteS (f, '" */');
WriteNl (f);
END;
END;
END;
(* gib die semantische Aktion zeilenweise aus *)
i1 := 2;
WHILE NOT IsEmpty (a) DO
StringMem.GetString (tStringRef (Head (a)), s);
i2 := Length (s);
Tail (a);
IF IsEmpty (a) THEN DEC (i2); END;
IF Language = Modula2 THEN WriteS (f, ' '); END;
i := i1;
WHILE i <= i2 DO
c := Char (s, i); INC (i);
IF c = '\' THEN
WriteC (f, Char (s, i)); INC (i);
ELSIF (c = '"') OR (c = "'") THEN
Delimiter := c;
WriteC (f, c);
REPEAT
c := Char (s, i); INC (i);
WriteC (f, c);
IF (Language = C) AND (c = '\') THEN
WriteC (f, Char (s, i)); INC (i);
END;
UNTIL c = Delimiter;
ELSIF c = '$' THEN (* evtl. Attribute *)
IF (i <= i2) AND (Char (s, i) = '$') THEN
WriteS (f, 'yySynAttribute');
INC (i);
ELSE
AttrIndex := 0;
IF (i <= i2) AND (Char (s, i) = '-') THEN
negative := TRUE;
INC (i);
ELSE
negative := FALSE;
END;
WHILE (i <= i2) AND (Char (s, i) >= '0') AND (Char (s, i) <= '9') DO
AttrIndex := AttrIndex * 10 + (ORD (Char (s, i)) - ORD('0'));
INC (i);
END;
IF negative OR (AttrIndex <= len) THEN
IF Language = Modula2 THEN
WriteS (f, 'yyAttributeStack^[yyStackPtr');
IF negative THEN WriteS (f, '-'); ELSE WriteS (f, '+'); END;
WriteI (f, AttrIndex, 0);
WriteS (f, ']');
ELSE (* Language = C *)
WriteS (f, 'yyAttrStackPtr [');
IF negative THEN WriteS (f, '-'); END;
WriteI (f, AttrIndex, 0);
WriteS (f, '-1]');
END;
ELSE (* Index unbrauchbar -> Kopie in Ausgabe *)
WriteC (f, c);
END;
END;
ELSE
WriteC (f, c);
END;
END;
i1 := 1;
END;
WriteNl (f);
END WriteSemanticAction;
PROCEDURE WriteProdComment (f: tFile; prod: tProduction);
VAR i: tIndex;
BEGIN
IF Language = Modula2 THEN
WriteS (f, ' (* ');
ELSE (* Language = C *)
WriteS (f, ' /* ');
END;
WITH prod^ DO
WriteToken (f, Left);
WriteS (f, ': ');
FOR i := 1 TO Len DO
WriteToken (f, Right[i]);
END;
WriteC (f, '.');
END;
IF Language = Modula2 THEN
WriteS (f, '*)');
WriteNl (f);
ELSE (* Language = C *)
WriteS (f, '*/');
WriteNl (f);
END;
END WriteProdComment;
PROCEDURE WriteToken (f: tFile; t: Vocabulary);
VAR
s: tString;
sym: tIdent;
error: TokenError;
i: CARDINAL;
BEGIN
sym := TokenToSymbol (t, error);
GetString (sym, s);
WriteC (f, Char (s, 1));
IF Language = Modula2 THEN
FOR i := 2 TO Length (s) DO
IF Char (s, i) = ')' THEN
IF Char (s, i-1) = '*' THEN
WriteC (f, ' ');
END;
ELSIF Char (s, i) = '*' THEN
IF Char (s, i-1) = '(' THEN
WriteC (f, ' ');
END;
END;
WriteC (f, Char (s, i));
END;
ELSE (* Language = C *)
FOR i := 2 TO Length (s) DO
IF Char (s, i) = '/' THEN
IF Char (s, i-1) = '*' THEN
WriteC (f, ' ');
END;
ELSIF Char (s, i) = '*' THEN
IF Char (s, i-1) = '/' THEN
WriteC (f, ' ');
END;
END;
WriteC (f, Char (s, i));
END;
END;
WriteC (f, ' ');
END WriteToken;
PROCEDURE WriteLong (f:tFile; Check:LONGINT);
VAR
i, j: LONGINT;
d: CARDINAL;
BEGIN
IF Check < 0 THEN
WriteC (f, '-');
Check := - Check;
END;
i := 1;
WHILE i <= Check DIV 10 DO
i := i * 10;
END;
WHILE i > 0 DO
d := Check DIV i;
WriteC (f, CHR(ORD('0')+d));
j := d;
DEC (Check, j * i);
i := i DIV 10;
END;
END WriteLong;
END GenLang.